package com.itheima.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Order(1) //多个切面时，通过Order注解设置切面执行顺序
@Slf4j
@Component
//@Aspect
public class MyAspect {

    //通过@Pointcut()注解 抽取公共切点表达式
    //execution(* com.itheima.service.impl.DeptServiceImpl.*(..))
    //第一个* 表示返回类型
    //第二个* 表示包名
    //第三个* 表示类名
    //第四个* 表示方法名
    //(..) 表示任意参数
    //DeptServiceImpl 类中所有方法
    @Pointcut("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
    private void pointcut() {
        log.info("pointcut 切点表达式");
    }

    //环绕通知 执行目标方法之前和之后都会执行
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("around 环绕通知");
        Object result = joinPoint.proceed();//执行目标方法,并返回结果
        return result;
    }

    //前置通知 执行目标方法之前
    @Before("pointcut()")
    public void before() {
        log.info("before 前置通知");
    }

    //后置通知 执行目标方法之后,无论是否发生异常都会执行
    @After("pointcut()")
    public void after() { //该方法无论是否发生异常都会执行
        log.info("after 后置通知");
    }

    //返回通知 执行目标方法正常返回之后执行
    @AfterReturning("pointcut()")
    public void afterReturning() {
        log.info("afterReturning 返回通知");
    }

    //异常通知 执行目标方法发生异常之后执行
    @AfterThrowing("pointcut()")
    public void afterThrowing() {
        log.info("afterThrowing 异常通知");
    }

}
